#pragma once

#include <iostream>
#include <assert.h>
#include <mutex>
#include <vector>
#include <thread>
#include <atomic>
#include <chrono>
#include <cstdlib>
#include <cstring>

// 内存管理常量定义
static const size_t MAX_BYTES = 256 * 1024;   // ThreadCache能申请的最大空间256KB
static const size_t NFREELIST = 208;         // 自由链表个数
static const size_t NPAGES = 129;            // PageCache里最大的页个数
static const size_t PAGE_SHIFT = 12;         // 一页的大小是2^PAGE_SHIFT字节，即4K
#define PAGESIZE (4*1024)                    // 每页大小4KB
#define SHIFTPAGE 12                         // 页大小位移数

// 跨平台PageId类型定义
#ifdef _WIN64
typedef unsigned long long PageId;  // 64-bit Windows系统
#elif _WIN32
typedef size_t PageId;              // 32-bit Windows系统
#elif __linux__
typedef unsigned long PAGE_ID;      // Linux系统
#elif __APPLE__
typedef size_t PageId;             // macOS系统
#else
#error "Unknown platform"
#endif

// 平台相关头文件
#ifdef _WIN32
#include <windows.h>
#else
#include <sys/mman.h>
#include <unistd.h>
#include <fcntl.h>
#endif

#include <stdexcept> // for std::bad_alloc

// 系统内存分配和释放函数
inline static void* SystemAlloc(size_t kpage) {
#ifdef _WIN32
    void* ptr = VirtualAlloc(0, kpage * 4 * 1024, MEM_COMMIT | MEM_RESERVE, PAGE_READWRITE);
#else
    // Linux/macOS使用mmap分配内存
    void* ptr = mmap(nullptr, kpage * 4 * 1024, PROT_READ | PROT_WRITE, 
                    MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
    if (ptr == MAP_FAILED) {
        perror("mmap failed");
        exit(EXIT_FAILURE);
    }
#endif

    if (ptr == nullptr) {
        throw std::bad_alloc();
    }
    return ptr;
}

inline static void SystemFree(void* ptr, size_t kpage) {
    if (ptr == nullptr) {
        return;
    }
#ifdef _WIN32
    VirtualFree(ptr, 0, MEM_RELEASE);
#else
    // Linux/macOS使用munmap释放内存
    size_t size = kpage * 4 * 1024;
    if (munmap(ptr, size) == -1) {
        perror("munmap failed");
        exit(EXIT_FAILURE);
    }
#endif
}

#include "ObjectPool.h"

// 获取对象的下一个指针
static void*& NextObj(void* obj) {
    return *(void**)obj;
}

/**
 * 自由链表类 - 管理切分好的小对象内存块
 * 功能：
 * 1. 管理空闲内存块的链表
 * 2. 支持单个对象的push/pop操作
 * 3. 支持批量对象的push/pop操作
 */
class FreeList {
public:
    // 将单个对象插入自由链表(头插法)
    void Push(void* obj) {
        assert(obj);
        NextObj(obj) = _freeList;
        _freeList = obj;
        ++_size;
    }

    // 批量插入对象范围到自由链表
    void PushRange(void* start, void* end, size_t n) {
        NextObj(end) = _freeList;
        _freeList = start;
        _size += n;
    }

    // 批量从自由链表取出对象范围
    void PopRange(void*& start, void*& end, size_t n) {
        assert(n <= _size);
        start = _freeList;
        end = start;

        for (size_t i = 0; i < n - 1; ++i) {
            end = NextObj(end);
        }

        _freeList = NextObj(end);
        NextObj(end) = nullptr;
        _size -= n;
    }

    // 从自由链表取出单个对象(头删法)
    void* Pop() {
        assert(_freeList);
        void* obj = _freeList;
        _freeList = NextObj(obj);
        --_size;
        return obj;
    }

    // 判断自由链表是否为空
    bool Empty() {
        return _freeList == nullptr;
    }

    // 获取/设置最大可缓存大小(慢启动用)
    size_t& MaxSize() {
        return _maxSize;
    }

    // 获取当前自由链表大小
    size_t Size() {
        return _size;
    }

private:
    void* _freeList = nullptr;  // 自由链表头指针
    size_t _maxSize = 1;        // 最大可缓存大小(慢启动)
    size_t _size = 0;           // 当前自由链表中的对象数量
};

/**
 * 大小对齐和索引计算类
 * 功能：
 * 1. 计算对象对齐后的大小
 * 2. 计算对象在自由链表中的索引
 * 3. 计算批量移动对象的数量
 */
class SizeClass {
public:
    // 内存分配对齐规则：
    // [1,128]字节        8字节对齐      freelist[0,16)
    // [129,1024]字节     16字节对齐     freelist[16,72)
    // [1025,8K]字节      128字节对齐    freelist[72,128)
    // [8K+1,64K]字节     1024字节对齐   freelist[128,184)
    // [64K+1,256K]字节   8K字节对齐     freelist[184,208)

    // 计算对齐后的大小(内联函数)
    static inline size_t _RoundUp(size_t bytes, size_t alignNum) {
        return ((bytes + alignNum - 1) & ~(alignNum - 1));
    }

    // 根据大小计算对齐后的大小
    static inline size_t RoundUp(size_t size) {
        if (size <= 128) {
            return _RoundUp(size, 8);
        } else if (size <= 1024) {
            return _RoundUp(size, 16);
        } else if (size <= 8*1024) {
            return _RoundUp(size, 128);
        } else if (size <= 64*1024) {
            return _RoundUp(size, 1024);
        } else if (size <= 256 * 1024) {
            return _RoundUp(size, 8*1024);
        } else {
            return _RoundUp(size, 1<<PAGE_SHIFT);
        }
    }

    // 计算对象在自由链表中的索引(内联函数)
    static inline size_t _Index(size_t bytes, size_t align_shift) {
        return ((bytes + (1 << align_shift) - 1) >> align_shift) - 1;
    }

    // 根据对象大小计算对应的自由链表索引
    static inline size_t Index(size_t bytes) {
        assert(bytes <= MAX_BYTES);

        // 每个区间的自由链表数量
        static int group_array[4] = { 16, 56, 56, 56 };
        if (bytes <= 128) {
            return _Index(bytes, 3);
        } else if (bytes <= 1024) {
            return _Index(bytes - 128, 4) + group_array[0];
        } else if (bytes <= 8 * 1024) {
            return _Index(bytes - 1024, 7) + group_array[1] + group_array[0];
        } else if (bytes <= 64 * 1024) {
            return _Index(bytes - 8 * 1024, 10) + group_array[2] + group_array[1] + group_array[0];
        } else if (bytes <= 256 * 1024) {
            return _Index(bytes - 64 * 1024, 13) + group_array[3] + group_array[2] + group_array[1] + group_array[0];
        } else {
            assert(false);
        }
        return -1;
    }

    // 计算一次从中心缓存获取多少个对象(慢启动用)
    static size_t NumMoveSize(size_t size) {
        assert(size > 0);
        int num = MAX_BYTES / size;
        if (num < 2) num = 2;      // 最少2个
        if (num > 512) num = 512;   // 最多512个
        return num;
    }

    // 计算一次向系统获取多少页内存
    static size_t NumMovePage(size_t size) {
        size_t num = NumMoveSize(size);
        size_t npage = num * size;
        npage >>= PAGE_SHIFT;
        if (npage == 0) npage = 1;  // 至少1页
        return npage;
    }
};

/**
 * 跨度结构体 - 管理以页为单位的大块内存
 * 功能：
 * 1. 记录大块内存的起始页号和页数
 * 2. 管理切分好的小对象自由链表
 * 3. 跟踪内存使用情况
 */
struct Span {
    PAGE_ID _pageId = 0;     // 大块内存起始页的页号
    size_t  _n = 0;          // 页的数量
    
    Span* _next = nullptr;   // 双向链表指针
    Span* _prev = nullptr;
    
    size_t _objSize = 0;     // 切分的小对象大小
    size_t _useCount = 0;    // 已分配出去的小对象数量
    void* _freeList = nullptr; // 自由链表头指针
    
    bool _isUse = false;     // 是否正在被使用
};

/**
 * 跨度链表类 - 带头双向循环链表
 * 功能：
 * 1. 管理Span的生命周期
 * 2. 提供链表基本操作接口
 * 3. 线程安全访问控制
 */
class SpanList {
public:
    SpanList() {
        static ObjectPool<Span> spanPool;
        _head = spanPool.New();
        _head->_next = _head;
        _head->_prev = _head;
    }

    // 获取链表起始位置(第一个元素)
    Span* Begin() { return _head->_next; }
    
    // 获取链表结束位置(头节点)
    Span* End() { return _head; }
    
    // 判断链表是否为空
    bool Empty() { return _head->_next == _head; }
    
    // 在链表头部插入Span
    void PushFront(Span* span) { Insert(Begin(), span); }
    
    // 从链表头部取出Span
    Span* PopFront() {
        Span* front = _head->_next;
        Erase(front);
        return front;
    }
    
    // 在指定位置前插入新Span
    void Insert(Span* pos, Span* newSpan) {
        assert(pos && newSpan);
        Span* prev = pos->_prev;
        prev->_next = newSpan;
        newSpan->_prev = prev;
        newSpan->_next = pos;
        pos->_prev = newSpan;
    }
    
    // 从链表中删除指定Span
    void Erase(Span* pos) {
        assert(pos && pos != _head);
        Span* prev = pos->_prev;
        Span* next = pos->_next;
        prev->_next = next;
        next->_prev = prev;
    }

private:
    Span* _head;             // 链表头节点
public:
    std::mutex _mtx;         // 互斥锁，保证线程安全
};